home *** CD-ROM | disk | FTP | other *** search
/ Total Web Page (Professional Suite) / Total Web Page 99.iso / CGI / C_DOWNLOAD.CGI-S=TEXTCOUNTER&C=TXT&F=TCOUNTER.CPP < prev    next >
C/C++ Source or Header  |  1996-06-03  |  13KB  |  418 lines

  1. #include <iostream.h>
  2. #include <fstream.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <time.h>
  6. #include <unistd.h>
  7. /*****************************************************************************
  8. * TextCounter (C++ Version)     Version 1.3                                  *
  9. * Copyright 1996 Matt Wright    mattw@worldwidemart.com                      *
  10. * Created 03/14/96              Last Modified 03/28/97                       *
  11. * Matt's Script Archive, Inc.   http://www.worldwidemart.com/scripts/        *
  12. * Perl Version also available at Matt's Script Archive.                      *
  13. ******************************************************************************
  14. * COPYRIGHT NOTICE                                                           *
  15. * Copyright 1996 Matthew M. Wright  All Rights Reserved.                     *
  16. *                                                                            *
  17. * TextCounter may be used and modified free of charge by anyone so long as   *
  18. * this copyright notice and the comments above remain intact.  By using this *
  19. * code you agree to indemnify Matthew M. Wright from any liability that      *
  20. * might arise from it's use.                                                 *
  21. *                                                                            *
  22. * Selling the code for this program without prior written consent is         *
  23. * expressly forbidden.  In other words, please ask first before you try and  *
  24. * make money off of my program.                                              *
  25. *                                                                            *
  26. * Obtain permission before redistributing this software over the Internet or *
  27. * in any other medium.  In all cases copyright and header must remain intact.*
  28. *****************************************************************************/
  29. // Define Variables
  30.  
  31. // Data Dir is the directory on your server that you wish to store the 
  32. // count files in.  Each page that has the counter on it will have it's own 
  33. // file and a lock file will also be created in this directory.
  34.  
  35. const char data_dir[] = "/path/to/data/";
  36.  
  37. // Valid-URI allows you to set up the counter to only work under specific 
  38. // directories on your server.  Include any of these directories as they 
  39. // appear in a URI, into this array.  More information on URI's available in 
  40. // README.  num_valid_uri is the number of valid URI's you have in the array.
  41. // As it is currently set, both valid uri and invalid uri blank, all pages
  42. // will be allowed.
  43.  
  44. const int  num_valid_uri = 0;
  45. const char valid_uri[num_valid_uri][128] = { };
  46.  
  47. // Invalid-URI allows the owner of this script to set up the counter so 
  48. // that certain portions of the web server that may be included in Valid-URI 
  49. // cannot use the program.  Set num_invalid_uri to 0 and clear the array if
  50. // you don't want to use this.
  51.  
  52. const int  num_invalid_uri = 0;
  53. const char invalid_uri[num_invalid_uri][128] = { };
  54.  
  55. /****************************************************************************/
  56. // Set Options
  57.  
  58. // Show Link allows you to add a link around the counter to point to 
  59. // either instructions explaining to users how to set this up on the system 
  60. // (useful if a system administrator wants to allow anyone to set things up 
  61. // themselves).  Setting it to "" will make no link, otherwise put the URL
  62. // you want linked to the count here.
  63.  
  64. const char show_link[] = "http://www.worldwidemart.com/scripts/";
  65.  
  66. // When Auto-Create is enabled, users will be able to auto-create the 
  67. // count on their home pages by simply imbedding the Server Side Includes 
  68. // call.  Setting auto_create to 1 enables it, 0 will disable it. Only 
  69. // users in @valid_uri will be allowed to auto create.
  70.  
  71. const int auto_create = 1;
  72.  
  73. // Show Date will show the date of when the count began if you set this 
  74. // option to 1.  It will appear in yor document as [Count] hits since [Date].
  75. // Set this to 0 and it will simply return the [Count].
  76.  
  77. const int show_date = 1;
  78.  
  79. // Lock Seconds will define the number of seconds the script should sit 
  80. // and wait for the lock file to be gone before it will overwrite it if it 
  81. // is still there.  Every now and then a user will interrupt a page, causing 
  82. // the script to halt and leave a lock file in place before the lock file 
  83. // could be removed.  This defines how long it waits.  Nothing more than
  84. // 2 or 3 seconds should be needed.
  85.  
  86. const int lock_sec = 2;
  87.  
  88. // Padding Size define how many numbers will be shown as your count.  For 
  89. // instance, if you want your count to say 00065 and have the zeros padded 
  90. // up to five digits, then set pad_size = 5;  If the number goes higher 
  91. // than the pad_size, don't worry, there just won't be any zero's tacked 
  92. // onto the front.
  93.  
  94. const int pad_size = 5;
  95.  
  96. /****************************************************************************/
  97.  
  98. void main() {
  99.     // Declare variables and subroutines
  100.     char *count_page, *count_file, *lock_file;
  101.     char c, date[32];
  102.  
  103.     int i, count, count_page_len;
  104.  
  105.     ifstream count_in;
  106.     ofstream count_out;
  107.  
  108.     int  check_uri(char []);
  109.     void error(char [], char []);
  110.     void check_lock(char []);
  111.     void clean_up(char []);
  112.     void create(char []);
  113.     void print_count(int);
  114.  
  115.     // Print Content-type header for browser
  116.     cout << "Content-type: text/html\n\n";
  117.  
  118.     // Get the page location from the DOCUMENT_URI or QUERY_STRING
  119.     // environment variables.
  120.     if (!getenv("DOCUMENT_URI") && !getenv("QUERY_STRING"))
  121.         error("no_uri","X");
  122.  
  123.     // Get the count page's length and store the page name into count_page
  124.     if (strlen(getenv("QUERY_STRING")) > 0)
  125.     {
  126.         count_page_len = strlen(getenv("QUERY_STRING"));
  127.         count_page = new char[count_page_len];
  128.         strcat(count_page,getenv("QUERY_STRING"));
  129.     }
  130.     else
  131.     {
  132.         count_page_len = strlen(getenv("DOCUMENT_URI"));
  133.         count_page = new char[count_page_len];
  134.         strcat(count_page,getenv("DOCUMENT_URI"));
  135.     }
  136.  
  137.     // Check Valid-URI to make sure user can use this program.
  138.     if (!check_uri(count_page))
  139.         error("bad_uri","X");
  140.  
  141.     // Convert '/',':','\' to '_' to avoid directory characters.
  142.     // || count_page[i] == ':' || count_page == '\'
  143.     for (i = 0; i < count_page_len; i++)
  144.         if (count_page[i] == '/')
  145.             count_page[i] = '_';
  146.  
  147.     // Generate the lock filename.
  148.     lock_file = new char[count_page_len + 4];
  149.     strcat(lock_file,data_dir);
  150.     strcat(lock_file,count_page);
  151.     strcat(lock_file,".lck");
  152.  
  153.     // Check to see if file is locked by program already in use.
  154.     check_lock(lock_file);
  155.  
  156.     // Generate the filename for the count page's data file.
  157.     count_file = new char[count_page_len + strlen(data_dir)];
  158.     strcat(count_file,data_dir);
  159.     strcat(count_file,count_page);
  160.  
  161.     // If the file exists, get the date and count out of it.  Otherwise, if 
  162.     // auto_create is allowed, create a new account.  If neither of these are 
  163.     // true, return an error.
  164.  
  165.     count_in.open(count_file);
  166.  
  167.     if (!count_in.fail())
  168.     {
  169.  
  170.         // Read in the current count.
  171.         count_in >> count;
  172.  
  173.         // Skip a character and read in next one to begin loop.
  174.         count_in.get(c);
  175.         count_in.get(c);
  176.  
  177.         // Read in the date until the end of file or a new line.
  178.         i = 0;
  179.         while (!count_in.eof() && c != '\n')
  180.         {
  181.             date[i] = c;
  182.             count_in.get(c);
  183.             i++;
  184.         }
  185.     }
  186.     else if (auto_create)
  187.     {
  188.         count_in.close();
  189.         create(count_file);
  190.     }
  191.     else
  192.     {
  193.         count_in.close();
  194.         error("page_not_found","X");
  195.     }
  196.  
  197.     // If the program got this far, close the file, since it hasn't been yet.
  198.     count_in.close();
  199.  
  200.     // Increment Count.
  201.     count++;
  202.  
  203.     // Print the Count, Link and Date depending on what user has specified 
  204.     // they wish to print.
  205.  
  206.     if (strlen(show_link) > 0)
  207.         cout << "<a href=\"" << show_link << "\">";
  208.  
  209.     print_count(count);
  210.  
  211.     if (strlen(show_link) > 0)
  212.         cout << "</a>";
  213.  
  214.     if (show_date)
  215.         cout << " hits since " << date;
  216.  
  217.     // Open the count file and write the new count that has been incremented.
  218.  
  219.     count_out.open(count_file);
  220.  
  221.     if (count_out.fail())
  222.         error("could_not_increment",count_file);
  223.     else
  224.         count_out << count << " " << date;
  225.  
  226.     count_out.close();
  227.  
  228.     // Remove Lock File for next time script is run on that HTML page.
  229.     clean_up(lock_file);
  230. }
  231.  
  232. int check_uri(char uri[]) {
  233.  
  234.     // Declare variables
  235.     int st = 0, uri_check = 0;
  236.     int valid_uri_len, invalid_uri_len, i, j;
  237.  
  238.     // For each valid URI, check to see if the current uri is included in that
  239.     // valid URI.  If so, set the uri check flag to 1 and break out of loop.
  240.     for (i = 0; i < num_valid_uri; i++)
  241.     {
  242.         valid_uri_len = strlen(valid_uri[i]);
  243.         for (j = 0; j < valid_uri_len; j++)
  244.         {
  245.             if (valid_uri[i][j] == uri[st])
  246.                 st++;
  247.             else
  248.                 st = 0;
  249.  
  250.             if (st == valid_uri_len)
  251.             {
  252.                 uri_check = 1;
  253.                 break;
  254.             }
  255.         }
  256.     }
  257.  
  258.     // Reset counter st.
  259.     st = 0;
  260.  
  261.     // For each invalid URI, check to see if current uri is included in that
  262.     // invalid URI.  If so, set the uri check flag to 0 and break out of loop.
  263.     for (i = 0; i < num_invalid_uri; i++)
  264.     {
  265.         invalid_uri_len = strlen(invalid_uri[i]);
  266.         for (j = 0; j < invalid_uri_len; j++)
  267.         {
  268.             if (invalid_uri[i][j] == uri[st])
  269.                 st++;
  270.             else
  271.                 st = 0;
  272.  
  273.             if (st == invalid_uri_len)
  274.             {
  275.                 uri_check = 0;
  276.                 break;
  277.             }
  278.         }
  279.     }
  280.  
  281.     // If both num_valid_uri and num_invalid_uri are set to 0, set the uri
  282.     // check flag to 1, because it is possible QUERY_STRING is being used.
  283.     if (!num_valid_uri && !num_invalid_uri)
  284.         uri_check = 1;
  285.  
  286.     // Return the uri check flag value.
  287.     return uri_check;
  288. }
  289.  
  290. void create(char count_file[])
  291. {
  292.     // Declare variables and subroutines.
  293.     char *date;
  294.     char months[12][10] = { "January", "February", "March", "April", "May",
  295.                             "June", "July", "August", "September", "October",
  296.                             "November", "December" };
  297.  
  298.     tm *ptm;
  299.     time_t *cur_time;
  300.  
  301.     ofstream count_out;
  302.  
  303.     void error(char [], char []);
  304.     void print_count(int);
  305.  
  306.     // Set up the memory for the time and time time struct.
  307.     cur_time = new time_t;
  308.     ptm = new tm;
  309.  
  310.     // Get the time, then create the struct with time values.
  311.     time(cur_time);
  312.     ptm = localtime(cur_time);
  313.  
  314.     // Write to the file, sending back an error if it fails.
  315.     count_out.open(count_file);
  316.  
  317.     if (count_out.fail())
  318.         error("count_not_created",count_file);
  319.     else
  320.         count_out << 1 << " " << months[ptm->tm_mon] << " " << ptm->tm_mday << ", " << ptm->tm_year + 1900;
  321.  
  322.     count_out.close();
  323.  
  324.     // Print the Count, Link and Date depending on what user has specified 
  325.     // they wish to print.
  326.  
  327.     if (strlen(show_link) > 0)
  328.         cout << "<a href=\"" << show_link << "\">";
  329.  
  330.     print_count(1);
  331.  
  332.     if (strlen(show_link) > 0)
  333.         cout << "</a>";
  334.  
  335.     if (show_date)
  336.         cout << " hits since " << months[ptm->tm_mon] << " " << ptm->tm_mday << ", " << ptm->tm_year + 1900;
  337. ;
  338.  
  339.     exit(0);
  340. }
  341.  
  342. void print_count(int count)
  343. {
  344.     // Declare variables.
  345.     int i, size = 0;
  346.     float count_tmp = count;
  347.  
  348.     // This determines the size of the count integer by divinding by 10 until
  349.     // the result is less than 1.
  350.     while (count_tmp >= 1)
  351.     {
  352.         count_tmp /= 10;
  353.         size++;
  354.     }
  355.  
  356.     // Pad the number with 0's if pad_size is greater than the count size.
  357.     for (i = 0; i < (pad_size - size); i++)
  358.         cout << 0;
  359.  
  360.     // Print the count.
  361.     cout << count;
  362. }
  363.  
  364. void error(char error[], char opt_file[])
  365. {
  366.     // Determine which flag was set and output appropriate error.
  367.     if (strcmp(error,"page_not_found") == 0)
  368.         cout << "[TextCounter Fatal Error: This Page Not Found; Auto-Create Option Disabled]";
  369.     else if (strcmp(error,"no_uri") == 0)
  370.         cout << "[TextCounter Fatal Error: No Document URI or File Flag specified]";
  371.     else if (strcmp(error,"bad_uri") == 0)
  372.         cout << "[TextCounter Fatal Error: This Page Not In Valid URI]";
  373.     else if (strcmp(error,"count_not_created") == 0)
  374.         cout << "[TextCounter Fatal Error: Could Not Write to File " << opt_file << "]";
  375.     else if (strcmp(error,"could_not_increment") == 0)
  376.         cout << "[TextCounter Fatal Error: Could Not Increment Counter File " << opt_file << "]";
  377.  
  378.     exit(0);
  379. }
  380.  
  381. void check_lock(char lock_file[])
  382. {
  383.     // Declare variables.
  384.     int i;
  385.  
  386.     ifstream test_in;
  387.     ofstream test_out;
  388.  
  389.     // For the number of seconds defined in lock_sec...
  390.     for (i = 1; i <= lock_sec; i++)
  391.     {
  392.         // Open the file for reading.
  393.         test_in.open(lock_file);
  394.  
  395.         // If that fails, the lock file doesn't exis.  We create the lock file
  396.         // and exit the loop.  Otherwise sleep for a second.
  397.         if (test_in.fail())
  398.         {
  399.             test_out.open(lock_file);
  400.             test_out << 0;
  401.             test_out.close();
  402.             break;
  403.         }
  404.         else
  405.             sleep(1);
  406.  
  407.         // Close the file if it is still open.
  408.         test_in.close();
  409.     }
  410. }
  411.  
  412. void clean_up(char lock_file[])
  413. {
  414.     // Remove the lock file.
  415.     unlink(lock_file);
  416.     exit(0);
  417. }
  418.